﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Web;

namespace Hangout.Web.Core.Location
{
    public class UserLocation
    {

        public static Model.Location UpdateUserLocation(Model.Location location,ref Model.HangoutDBEntities context)
        {

            bool localityChanged = false;

            bool flag = false;

            Model.Location l=GetLastLocation((int)location.UserID,ref context);

            if (l == null)
            {
                l = new Model.Location();
                flag = true;
                l.UserID = location.UserID;
               
            }

            l.Latitude = location.Latitude;
            l.Longitude = location.Longitude;
            l.DateTimeStamp = DateTime.Now;

            ReverseGeocodeRequest(ref l,ref localityChanged);
           

            

            if (flag)
            {
                context.AddToLocations(l); //add it to the context :)
            }

            context.SaveChanges(); //save changes

            if (flag)
            {
                if (location.UserID != null)
                {
                    Core.Cloud.Queue.GetCompatibility((int)location.UserID);
                }
            }
            else
            {
                if (localityChanged)
                {
                    if (location.UserID != null)
                    {
                        Core.Cloud.Queue.GetCompatibility((int)location.UserID);
                    }
                }
            }


            return l;

            
        }

        private static void ReverseGeocodeRequest(ref Model.Location l,ref bool localityChanged)
        {
            GeocodeService.GeocodeServiceClient client = new GeocodeService.GeocodeServiceClient("BasicHttpBinding_IGeocodeService");
            var response = client.ReverseGeocode(new GeocodeService.ReverseGeocodeRequest { Location = new GeocodeService.Location { Latitude = l.Latitude, Longitude = l.Longitude }, Credentials = new GeocodeService.Credentials { ApplicationId="ArUCmVVpgJv12YfInKr0GtEhFhE4SjXGbxdShaJBbneeWIXfUZ5HtdA2GsRFm_U7"} });
            if (response.Results.Count() > 0)
            {
                var result = response.Results[0].Address;
                l.AddressLine = result.AddressLine;
                l.FormattedAddress = result.FormattedAddress;
                l.AdminDistrict = result.AdminDistrict;
                l.CountryRegion = result.CountryRegion;
                l.District = result.District;
                l.PostalCode = result.PostalCode;
                l.PostalTown = result.PostalTown;

                if (l.Locality != null)
                {
                    if (l.Locality != result.Locality)
                    {
                        localityChanged = true;
                    }
                }
                l.Locality = result.Locality;

            }
        }

        

        public static List<UserLocationData> GetNearestUsers(int userid,int radius,ref Model.HangoutDBEntities context)
        {
            Model.Location lastLocation = GetLastLocation(userid, ref context);

            if (lastLocation == null)
            {
                return new List<UserLocationData>();
            }

            if(lastLocation.Locality==null)
            {
                return new List<UserLocationData>();
            }

            List<int> userIds = context.Locations.Where(o => o.Locality == lastLocation.Locality&&o.UserID!=null).Select(o => o.UserID.Value).ToList();

            if (userIds.Contains(userid))
            {
                userIds.Remove(userid);
            }

            List<UserLocationData> locationData = new List<UserLocationData>();

            foreach (int userId in userIds)
            {
                UserLocationData data = new UserLocationData();
                data.UserData = Core.Accounts.User.GetUserData(userId, ref context);
                

                if (data.UserData.Profile == null)
                {
                    continue;
                }
                data.location = GetLastLocation(userid, ref context);
                if (data.location == null)
                {
                    continue;
                }


                locationData.Add(data);
                
            }

            return locationData;

            
        }

        public static Model.Location GetLastLocation(int userid, ref Model.HangoutDBEntities context)
        {
            return context.Locations.Where(o => o.UserID == userid).ToList().LastOrDefault();
        }

        public static Model.Location GetCurrentLocation(int userid, ref Model.HangoutDBEntities context)
        {
            return context.Locations.Where(o => o.UserID == userid && (EntityFunctions.DiffMinutes(DateTime.Now, o.DateTimeStamp) <= 30)).ToList().LastOrDefault();
        }

        public static Model.Location InsertLocation(Model.Location location,ref Model.HangoutDBEntities context)
        {
            bool localityChanged = false;
            if (location != null)
            {
                Model.Location l = new Model.Location();
                l.Altitude = location.Altitude;
                l.ClientDateTimeStamp = location.ClientDateTimeStamp;
                l.Course = location.Course;
                l.DateTimeStamp = DateTime.Now;
                l.HorizontalAccuracy = location.HorizontalAccuracy;
                l.Latitude = location.Latitude;
                l.Longitude = location.Longitude;
                l.Speed = location.Speed;
                l.VerticalAccuracy = location.VerticalAccuracy;

                ReverseGeocodeRequest(ref l,ref localityChanged);

                context.AddToLocations(l);
                context.SaveChanges();

                

                return l;
            }

            return null;
        }
    }
}